﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using OpenNETCF.Security.Cryptography;
using System.Security.Cryptography;
using System.Web;
using System.Net;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Specialized;
using foursquare;
using System.Xml;

namespace foursquare
{
    /// <summary>
    /// FSHelper class is contains helper methods for OAuth system
    /// </summary>
    public class FSHelper
    {
        /// <summary>
        /// GenerateTimeStamp method generates TimeStamp value.
        /// </summary>
        /// <returns></returns>
        public string GenerateTimeStamp()
        {

            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0));
            string timeStamp = Convert.ToInt64(ts.TotalSeconds).ToString();
            return timeStamp;
        }
        /// <summary>
        /// Nonce is a unique string based value. GetNonce method generates this value
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public string GetNonce(int length)
        {
            string allowedCharacters = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789";
            StringBuilder password = new StringBuilder();
            Random rand = new Random();

            for (int i = 0; i < length; i++)
            {
                password.Append(allowedCharacters[rand.Next(0, (allowedCharacters.Length - 1))]);
            }
            return password.ToString();

        }
    }

    public static class FSOAuth
    {
        /// <summary>
        /// consumerKey
        /// </summary>
        private static string consumerKey = "EIYWN35RDVLJ20UWFHEKG0UNHCK34ITOUNT4GXLOW5HZRXE5";

        /// <summary>
        /// consumerSecret
        /// </summary>
        private static string consumerSecret = "LVAGI5ALX4FR5ESYZAIGYHYHYVVDDZ1GF2MKAJS332W5JAKO";

        public static bool Login(string userName, string passWord, out string message)
        {
            Uri uri = new Uri("http://api.foursquare.com/v1/authexchange");

            FSHelper helper = new FSHelper();
            ASCIIEncoding encoding = new ASCIIEncoding();

            HMACSHA1 sha1 = new HMACSHA1();
            byte[] key = Encoding.ASCII.GetBytes(consumerSecret + "&" + "");
            if (key.Length > 64)
            {

                SHA1CryptoServiceProvider coreSha1 = new SHA1CryptoServiceProvider();
                key = coreSha1.ComputeHash(key);
            }
            sha1.Key = key;

            string timeStamp = helper.GenerateTimeStamp();
            System.Collections.Generic.List<string> parameters = new System.Collections.Generic.List<string>();

            parameters.Add("oauth_consumer_key=" + HttpUtility.UrlEncode(consumerKey));
            parameters.Add("oauth_nonce=" + HttpUtility.UrlEncode(helper.GetNonce(7)));
            parameters.Add("oauth_timestamp=" + timeStamp);
            parameters.Add("oauth_signature_method=HMAC-SHA1");
            parameters.Add("oauth_version=1.0");
            parameters.Add("fs_username=" + userName);
            parameters.Add("fs_password=" + passWord);

            parameters.Sort();
            string parametersStr = string.Join("&", parameters.ToArray());


            string baseStr = "GET" + "&" +
                HttpUtility.UrlEncode(uri.ToString()) + "&" +
                HttpUtility.UrlEncode(parametersStr);


            byte[] baseStringBytes = Encoding.UTF8.GetBytes(baseStr.Replace("%3d", "%3D").Replace("%3a", "%3A").Replace("%2f", "%2F"));
            byte[] baseStringHash = sha1.ComputeHash(baseStringBytes);
            String base64StringHash = Convert.ToBase64String(baseStringHash);
            String encBase64StringHash = HttpUtility.UrlEncode(base64StringHash);

            parameters.Add("oauth_signature=" + encBase64StringHash);
            parameters.Sort();

            string requestUrl = uri.ToString() + "?" + string.Join("&", parameters.ToArray());
            HttpWebRequest r = (HttpWebRequest)HttpWebRequest.Create(requestUrl);

            r.Method = "GET";

            r.ContentType = "application/x-www-form-urlencoded";

            try
            {

                HttpWebResponse response = (HttpWebResponse)r.GetResponse();
                UserName = userName;
                Password = passWord;

                string cevap = new StreamReader(response.GetResponseStream()).ReadToEnd();

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(cevap);

                oauth_token = doc.SelectSingleNode("//oauth_token").InnerText;
                oauth_token_secret = doc.SelectSingleNode("//oauth_token_secret").InnerText;

                response.Close();
                FS.OAuthToken = oauth_token;
                FS.OAuthTokenSecret = oauth_token_secret;
                message = cevap;
                return true;
            }
            catch (WebException ex)
            {
                message = ex.Message;
                return false;
            }
        }
        
        public static bool UserRequest(string url, string userName, string passWord, string oauth_token, string oauth_token_secret, List<string> param, string httpMethod, out string message)
        {
            Uri uri = new Uri(url);
            FSHelper helper = new FSHelper();

            ASCIIEncoding encoding = new ASCIIEncoding();

            HMACSHA1 sha1 = new HMACSHA1();
            byte[] key = Encoding.ASCII.GetBytes(consumerSecret + "&" + oauth_token_secret);
            if (key.Length > 64)
            {

                SHA1CryptoServiceProvider coreSha1 = new SHA1CryptoServiceProvider();
                key = coreSha1.ComputeHash(key);
            }
            sha1.Key = key;

            string timeStamp = helper.GenerateTimeStamp();
            System.Collections.Generic.List<string> parameters = new System.Collections.Generic.List<string>();

            parameters.Add("oauth_consumer_key=" + HttpUtility.UrlEncode(consumerKey));
            parameters.Add("oauth_nonce=" + HttpUtility.UrlEncode(helper.GetNonce(7)));
            parameters.Add("oauth_timestamp=" + timeStamp);
            parameters.Add("oauth_signature_method=HMAC-SHA1");
            parameters.Add("oauth_version=1.0");
            parameters.Add("oauth_token=" + HttpUtility.UrlEncode(oauth_token));
            if (param != null)
                parameters.AddRange(param);

            parameters.Sort();
            string parametersStr = string.Join("&", parameters.ToArray());


            string baseStr = httpMethod + "&" +
                 HttpUtility.UrlEncode(uri.ToString()) + "&" +
                HttpUtility.UrlEncode(parametersStr);

            /* generate the signature and add it to our parameters */
            string lastString = baseStr.Replace("%3d", "%3D").Replace("%3a", "%3A").Replace("%2f", "%2F").Replace("(", "%2528").Replace(")", "%2529");
            byte[] baseStringBytes = Encoding.ASCII.GetBytes(lastString);
            byte[] baseStringHash = sha1.ComputeHash(baseStringBytes);
            String base64StringHash = Convert.ToBase64String(baseStringHash);
            String encBase64StringHash = HttpUtility.UrlEncode(base64StringHash);

            parameters.Add("oauth_signature=" + encBase64StringHash);
            parameters.Sort();
            HttpWebRequest r = null;
            string requestUrl = uri.ToString() + "?" + string.Join("&", parameters.ToArray());
            if (httpMethod == "GET")
            {

                r = (HttpWebRequest)HttpWebRequest.Create(requestUrl);
                r.Method = httpMethod;
                r.ContentType = "application/x-www-form-urlencoded";

            }
            else if (httpMethod == "POST")
            {
                parametersStr = string.Join("&", parameters.ToArray());

                string normalizedUrl = string.Format("{0}://{1}", uri.Scheme, uri.Host);
                if (!((uri.Scheme == "http" && uri.Port == 80) || (uri.Scheme == "https" && uri.Port == 443)))
                {
                    normalizedUrl += ":" + uri.Port;
                }
                normalizedUrl += uri.AbsolutePath;

                r = (HttpWebRequest)HttpWebRequest.Create(normalizedUrl);

                r.ContentType = "application/x-www-form-urlencoded";

                byte[] bytes = Encoding.ASCII.GetBytes(parametersStr);
                r.ContentLength = bytes.Length;

                r.Method = httpMethod.ToUpper();
                Stream s = r.GetRequestStream();

                s.Write(bytes, 0, bytes.Length);

                s.Close();
            }

            try
            {
                WebResponse res = r.GetResponse();
                HttpWebResponse response = (HttpWebResponse)res;
                string cevap = new StreamReader(response.GetResponseStream()).ReadToEnd();

                response.Close();
                message = cevap;
                return true;
            }
            catch (WebException ex)
            {
                if (ex.Message == "This protocol version is not supported.")
                {
                    message = string.Empty;
                    return true;
                }

                message = ex.Message;
                return false;
            }
        }
        public static string UserName { get; set; }
        public static string Password { get; set; }
        public static string oauth_token { get; set; }
        public static string oauth_token_secret { get; set; }
    }

}
